--- title: "L1-049 天梯赛座位分配" created: 2025-11-28 tags: - 算法 --- # L1-049 天梯赛座位分配 ## 题目 [L1-049 天梯赛座位分配](https://pintia.cn/problem-sets/994805046380707840/exam/problems/type/7?problemSetProblemId=994805081289900032&page=0) ![[image-18766f6a.png]] ## 思路分析 ![[image-5091eb53.png]] 三个学校 分别有 3 4 2个队伍 首先初始化第一轮的排座 学校1的第一个学生坐1 学校2 的第一个学生坐2 学校三的第一个学生坐3 然后找到最少队伍的那个学校 有两个队伍 那就是可以以3为循环 安排到第 60号位置(分别在三个学校做等差数列) 学校一 首项为1 公差为3 推到60 得:1 4 7 10 13 16 19 22 25 28 31 34 37 40 43 46 49 52 55 58 学校二:首项为2 公差为3 推到60 2 5 8 11 14 17 20 23 26 29 32 35 38 41 44 47 50 53 56 59 学校三:首项为3 公差为3 推到60 得3 6 9 12 15 18 21 24 27 30 33 36 39 42 45 48 51 54 57 60 用优先队列或者有序set维护这个队伍 方便取出最大的作为下一轮的首项(第一轮也适用 因为123是事先填入的) 然后所有学校减去2个队伍(已经安排完) 还剩2个学校 分别为1 2个队伍 取到最少的1 乘上n(2) 得到20 60+20=80 那么继续往后推到第80个座位 学校一: 以上次安排完的最后一个位置开始 第61 公差为2 推到80 61 63 65 67 69 71 73 75 77 79 学校二:62 64 66 68 70 72 74 76 78 80 再减去10 还剩学校2有一个队伍 以公差为2做 到结束 82 84 86 88 90 92 94 96 98 100 ## 代码实现 ```cpp #include using namespace std; #define endl '\n' #define int long long using ll = long long; using ull = unsigned long long; using PII = pair; using Pll = pair; int dx[4] = { -1,0,1,0 }, dy[4] = { 0,1,0,-1 };h const int inf = 0x3f3f3f3f; signed main() { ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); int n; cin >> n; // 读入每所高校的队伍数,并初始化 st 向量 for (int i = 1; i <= n; i++) { cin >> m[i]; st.push_back({i, m[i]}); } // 按照队伍数从小到大排序(用于后续动态更新队伍最少的学校) sort(st.begin(), st.end(), [](pai a, pai b) { return a.second < b.second; }); // 对每一所学校 i,输出它的所有队伍安排 for (int i = 1; i <= n; i++) { cout << "#" << i << endl; int id = i; // 当前学校起始编号为 i,初始的首项 int k = n; // 当前还没排完的高校数量,初始为 n int v = 0; // 指向 st 中下一个队伍排完的学校 int dt = (n == 1) ? 2 : n; // 初始化公差,如果只有一所学校,公差为 2 否则为 n // 安排第 i 所高校的所有队伍 for (int x = 1; x <= m[i]; x++) { // 每支队伍安排 10 个人 for (int j = 1; j <= 10; j++) { cout << id; if (j != 10) cout << ' '; else puts(""); id += dt; // 更新座位号,等差 } // 检查是否有其他学校的队伍刚好也排完了(x == st[v].second) while (v < st.size() && x == st[v].second) { k--; // 一个学校排完,未完成的学校数减少 // 如果剩下不只当前学校,且当前学校编号在排完的学校之后,需要回退 1 位首项 // 这是为了防止座位冲突,确保后续等差排布不重叠 if (k != 1 && st[v].first < i) id--; v++; } // 更新新的公差 dt = (k == 1) ? 2 : k; } } return 0; } ``` ## 同类题型 ## 视频讲解 --- ⬅️ [[L1-048 矩阵A乘以B|L1-048 矩阵A乘以B]] 🏠 [[00-天梯赛]] ➡️ [[L1-050 倒数第N个字符串|L1-050 倒数第N个字符串]]